package com.example.gobang.api;

import com.example.gobang.game.MatchRequest;
import com.example.gobang.game.MatchResponse;
import com.example.gobang.game.Matcher;
import com.example.gobang.game.OnlineUserStatus;
import com.example.gobang.model.User;
import com.example.gobang.tool.ConStant;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;

//通过这个类来处理匹配功能中的 websocket 请求
@Component
public class MatchAPI extends TextWebSocketHandler {
    ObjectMapper objectMapper = new ObjectMapper();

    @Resource
    private OnlineUserStatus onlineUserStatus;

    @Resource
    private Matcher matcher;


    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线,就加入到 onlineUserStatus
        //1.获取到当前用户的身份信息(谁在游戏大厅中,建立了连接)
        // session.getAttributes() 获取到的是一个 Map 键值对
        // session.getAttributes().get() 得到的是 value 值
        //此处拿到的user有可能是空的,可能没通过 http 登录,直接通过 game_hall.html 登录来访问游戏大厅页面
        //此时就会出现 user 为空的情况
        try{
            User user = (User) session.getAttributes().get(ConStant.KEY_SESSION);

            //2.先判定当前用户是否已经登录过(已经是在线状态),如果是已经在线,就不该继续进行后续的逻辑.
            if(onlineUserStatus.getFromGameHall(user.getUserId()) != null ||
            onlineUserStatus.getFromGameRoom(user.getUserId()) != null){
                //当前用户已经登录
                //针对这个情况要告知客户端重复登录了
                MatchResponse matchResponse = new MatchResponse();
                matchResponse.setOk(true);
                matchResponse.setReason("当前禁止多开");
                matchResponse.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(matchResponse)));
                //主动断开连接,websocket 连接都没了,再想发什么匹配请求那肯定是没法发送的
                //此处直接关闭有些太激进了,凡是返回一个 特殊的 message ,供客户端来负责进行处理
                //session.close();
                return;
            }

            //3.拿到了身份信息之后,就可以把玩家设置成在线状态了
            onlineUserStatus.enterGameHall(user.getUserId(),session);
            System.out.println("玩家: " + user.getUsername() + " 进入了游戏大厅");
        }catch (NullPointerException e){
            System.out.println("MatchAPI.afterConnectionEstablished! 当前用户未登录!");
        }
            //e.printStackTrace();
            //出现空指针异常,说明当前用户的身份信息是空,用户未登录
            //把当前用户尚未登录这个信息给返回去
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("您尚未登录! 不能进行后续的匹配! ");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
//        }



    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //实现处理开始匹配请求和处理停止匹配请求
        User user = (User) session.getAttributes().get(ConStant.KEY_SESSION);
        //获取到客户端给服务器发送的数据
        String payload = message.getPayload();
        //当前这个数据载荷是一个 JSON 格式的字符串.就需要把它转成 Java 对象. MarchRequest
        MatchRequest matchRequest = objectMapper.readValue(payload, MatchRequest.class);
        MatchResponse matchResponse = new MatchResponse();
        if (matchRequest.getMessage().equals("startMatch")){
            //进入匹配队列
            //TODO 先创建一个类表示匹配队列,把当前用户给加进去
            matcher.add(user);
            //把玩家信息放入匹配队列之后,就可以返回一个响应给客户端了
            matchResponse.setOk(true);
            matchResponse.setMessage("startMatch");
        }else if(matchRequest.getMessage().equals("stopMatch")){
            //退出匹配队列
            //TODO 先创建一个类表示匹配队列,把当前用户从列表中移除
            matcher.remove(user);
            //移除之后,就可以返回一个响应给客户端了
            matchResponse.setOk(true);
            matchResponse.setMessage("stopMatch");
        }else{
            //非法情况
            matchResponse.setOk(false);
            matchResponse.setMessage("非法的匹配请求");
        }
        String jsonString = objectMapper.writeValueAsString(matchResponse);
        session.sendMessage(new TextMessage(jsonString));



    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        try{
            //玩家下线,就从 onlineUserStatus 中删除
            User user = (User) session.getAttributes().get(ConStant.KEY_SESSION);
            WebSocketSession tmpsession = onlineUserStatus.getFromGameHall(user.getUserId());
            if (tmpsession == session) {
                onlineUserStatus.exitsGameHall(user.getUserId());
            }
            //如果玩家正在匹配中,而 websocket 连接断开了,就应该移除匹配队列
            matcher.remove(user);

        }catch (NullPointerException e){
            System.out.println("MatchAPI.handleTransportError 当前用户未登录");
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("您尚未登录! 不能进行后续的匹配! ");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));

        }


    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try{

            //玩家下线,就从 onlineUserStatus 中删除
            User user = (User) session.getAttributes().get(ConStant.KEY_SESSION);
            WebSocketSession tmpsession = onlineUserStatus.getFromGameHall(user.getUserId());
            if (tmpsession == session) {
                onlineUserStatus.exitsGameHall(user.getUserId());
            }
            //如果玩家正在匹配中,而 websocket 连接断开了,就应该移除匹配队列
            matcher.remove(user);

        }catch (NullPointerException e){
            System.out.println("MatchAPI.afterConnectionClosed 当前用户未登录");
            //e.printStackTrace();
            //这个代码之前写的草率了
            //不应该在连接关闭之后,还尝试发送消息给客户端
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("您尚未登录! 不能进行后续的匹配! ");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));

        }
    }
}
